/*
* This file is a part of the open-eBackup project.
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
* If a copy of the MPL was not distributed with this file, You can obtain one at
* http://mozilla.org/MPL/2.0/.
*
* Copyright (c) [2024] Huawei Technologies Co.,Ltd.
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*/
#include "gtest/gtest.h"
#include "stub.h"
#include "gmock/gmock.h"
#include "gmock/gmock-actions.h"
#include "ChannelManager.h"

using namespace std;
using namespace NasChannelManager;
size_t NUMBER2 = 2;

class ChannelManagerTest : public testing::Test {
protected:
    void SetUp() override {}
    void TearDown() override {}
};

/*
* 用例名称：GetInstance
* 前置条件：无
* check点：需要返回单例
*/
TEST_F(ChannelManagerTest, GetInstance)
{
    ChannelManager &instance1 = ChannelManager::GetInstance();
    ChannelManager &instance2 = ChannelManager::GetInstance();
    EXPECT_EQ(&instance1, &instance2);
}

/*
* 用例名称：GetInstance_Nullptr
* 前置条件：无
* check点：需要返回非空实例
*/
TEST_F(ChannelManagerTest, GetInstance_Nullptr)
{
    ChannelManager &instance = ChannelManager::GetInstance();
    EXPECT_NE(&instance, nullptr);
}

/*
* 用例名称：AddSubJobToChannelManager
* 前置条件：无
* check点：需要添加子任务成功
*/
TEST_F(ChannelManagerTest, AddSubJob_success_for_one)
{
    std::string jobId = "job1";
    std::string subJobId = "subJob1";
    std::string numOfChannels = "2";
    bool result = ChannelManager::GetInstance().AcceptSubJob(jobId, subJobId, numOfChannels);
    ChannelManager::GetInstance().AddSubJob(jobId, subJobId);
    ASSERT_TRUE(result);
}

/*
* 用例名称：addSubJobToChannelManager
* 前置条件：无
* check点：需要添加子任务成功
*/
TEST_F(ChannelManagerTest, AddSubJob_success_for_two)
{
    std::string jobId = "job1";
    std::string subJobId = "subJob1";
    std::string numOfChannels = "2";
    ChannelManager::GetInstance().AcceptSubJob(jobId, subJobId, numOfChannels);
    ChannelManager::GetInstance().AddSubJob(jobId, subJobId);
    bool result = ChannelManager::GetInstance().AcceptSubJob(jobId, subJobId, numOfChannels);
    ChannelManager::GetInstance().AddSubJob(jobId, subJobId);
    ASSERT_TRUE(result);
}

/*
* 用例名称：addSubJobToChannelManager
* 前置条件：无
* check点：字符串解析失败使用默认通道数
*/
TEST_F(ChannelManagerTest, AddSubJob_success_for_bad_num)
{
    std::string jobId = "job1";
    std::string subJobId = "subJob1";
    std::string numOfChannels = "nonum";
    bool result = ChannelManager::GetInstance().AcceptSubJob(jobId, subJobId, numOfChannels);
    ChannelManager::GetInstance().AddSubJob(jobId, subJobId);
    ASSERT_FALSE(result);
}

/*
* 用例名称：AddSubJobToChannelManager
* 前置条件：无
* check点：需要添加子任务失败
*/
TEST_F(ChannelManagerTest, AddSubJob_fail)
{
    std::string jobId = "job1";
    std::string subJobId1 = "subJob1";
    std::string subJobId2 = "subJob2";
    std::string numOfChannels = "1";
    ChannelManager::GetInstance().AcceptSubJob(jobId, subJobId1, numOfChannels);
    ChannelManager::GetInstance().AddSubJob(jobId, subJobId1);
    bool result = ChannelManager::GetInstance().AcceptSubJob(jobId, subJobId2, numOfChannels);
    ASSERT_FALSE(result);
}

TEST_F(ChannelManagerTest, addSubJob_succ)
{
    std::string jobId = "job1";
    std::string subJobId1 = "subJob1";
    std::string subJobId2 = "subJob1";
    std::string numOfChannels = "2";
    ChannelManager::GetInstance().AcceptSubJob(jobId, subJobId1, numOfChannels);
    ChannelManager::GetInstance().AddSubJob(jobId, subJobId1);
    bool result = ChannelManager::GetInstance().AcceptSubJob(jobId, subJobId2, numOfChannels);
    ChannelManager::GetInstance().AddSubJob(jobId, subJobId2);
    ASSERT_TRUE(result);
}

TEST_F(ChannelManagerTest, RemoveSubJob_success)
{
    // Arrange
    std::string jobId = "job1";
    std::string subJobId = "subJob1";
    std::string numOfChannels = "2";
    ChannelManager::GetInstance().AcceptSubJob(jobId, subJobId, numOfChannels);
    ChannelManager::GetInstance().AddSubJob(jobId, subJobId);

    // Act
    ChannelManager::GetInstance().RemoveSubJob(jobId, subJobId);

    // Assert
    EXPECT_EQ(ChannelManager::GetInstance().GetSubJobCount(jobId), 0);
}

/*
* 用例名称：RemoveSubJobToChannelManager
* 前置条件：无
* check点：移除所有子任务
*/
TEST_F(ChannelManagerTest, RemoveSubJob_nullset)
{
    // Arrange
    std::string jobId1 = "job1";
    std::string jobId2 = "job2";
    std::string subJobId = "subJob1";
    std::string numOfChannels = "2";
    ChannelManager::GetInstance().AcceptSubJob(jobId1, subJobId, numOfChannels);
    ChannelManager::GetInstance().AddSubJob(jobId1, subJobId);
    ChannelManager::GetInstance().AcceptSubJob(jobId2, subJobId, numOfChannels);
    ChannelManager::GetInstance().AddSubJob(jobId2, subJobId);

    // Act
    ChannelManager::GetInstance().RemoveSubJob(jobId1, subJobId);

    // Assert
    EXPECT_EQ(ChannelManager::GetInstance().GetSubJobCount(jobId1), 0);
    EXPECT_EQ(ChannelManager::GetInstance().GetSubJobCount(jobId2), 1);
}

/*
* 用例名称：RemoveSubJobNotExist
* 前置条件：无
* check点：移除所有子任务
*/
TEST_F(ChannelManagerTest, RemoveSubJob_notRemove)
{
    // Arrange
    std::string jobId = "job1";
    std::string subJobId = "subJob1";
    std::string numOfChannels = "2";
    ChannelManager::GetInstance().AcceptSubJob(jobId, subJobId, numOfChannels);
    ChannelManager::GetInstance().AddSubJob(jobId, subJobId);

    // Act
    ChannelManager::GetInstance().RemoveSubJob(jobId, "nonExistingSubJob");

    // Assert
    EXPECT_EQ(ChannelManager::GetInstance().GetSubJobCount(jobId), 1);
}

/*
* 用例名称：getSubJobCountTest
* 前置条件：无
* check点：检查集合为空时的统计
*/
TEST_F(ChannelManagerTest, getSubJobCount_nullSet)
{
    std::string jobId = "non_existent_job_id";
    int subJobCount = ChannelManager::GetInstance().GetSubJobCount(jobId);
    EXPECT_EQ(subJobCount, 0);
}

/*
* 用例名称：getSubJobCountTest
* 前置条件：无
* check点：检查集合为2时的统计
*/
TEST_F(ChannelManagerTest, getSubJobCount_NotNullSet)
{
    std::string jobId = "existent_job_id";
    // Add jobId to m_subJobs map
    ChannelManager::GetInstance().m_subJobs[jobId] = {"subJob1", "subJob2"};
    int subJobCount = ChannelManager::GetInstance().GetSubJobCount(jobId);
    EXPECT_EQ(subJobCount, NUMBER2);
}